package com.idp.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.idp.common.enums.MessageEnum;
import com.idp.common.error.SystemException;
import com.idp.common.model.PageModel;
import com.idp.common.utils.ContextUtil;
import com.idp.system.dto.SysButtonDto;
import com.idp.system.dto.SysMenuDto;
import com.idp.system.dto.SysRoleDto;
import com.idp.system.dto.SysRoleSearchDto;
import com.idp.system.entity.SysRoleButtonEntity;
import com.idp.system.entity.SysRoleEntity;
import com.idp.system.entity.SysRoleMenuEntity;
import com.idp.system.entity.SysUserEntity;
import com.idp.system.mapper.*;
import com.idp.system.service.SysRoleService;
import com.idp.system.utils.MenuUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 角色Service实现类
 * @author king
 */
@Service
public class SysRoleServiceImpl implements SysRoleService {

	@Autowired
	private SysRoleMapper sysRoleMapper;
	@Autowired
	private SysUserRoleMapper sysUserRoleMapper;
	@Autowired
	private SysMenuMapper sysMenuMapper;
	@Autowired
	private SysRoleMenuMapper sysRoleMenuMapper;
	@Autowired
	private SysRoleButtonMapper sysRoleButtonMapper;

	@Override
	public PageModel<SysRoleDto> findByPage(SysRoleSearchDto sysRoleSearchDto) {

		PageModel<SysRoleDto> page = new PageModel<SysRoleDto>();

		page.setList(sysRoleMapper.getList(sysRoleSearchDto));

		return page;
	}

	@Override
	public SysRoleDto getById(String id) {

		if(StrUtil.isEmpty(id)) {

			throw new SystemException(MessageEnum.PARAM_ERROR);
		}

		SysRoleEntity sysRoleEntity = sysRoleMapper.selectById(id);

		if(sysRoleEntity == null) {

			throw new SystemException(MessageEnum.DATA_NOT_EXIST);
		}

		return BeanUtil.toBean(sysRoleEntity, SysRoleDto.class);
	}

	@Override
	@Transactional(rollbackFor=Exception.class)
	public void add(SysRoleDto sysRoleDto) {

		LambdaQueryWrapper<SysRoleEntity> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(SysRoleEntity::getRoleName, sysRoleDto.getRoleName());
		SysRoleEntity checkRole = sysRoleMapper.selectOne(queryWrapper);

		if(checkRole != null) {
			throw new SystemException("角色名称已存在");
		}

		SysRoleEntity sysRoleEntity = BeanUtil.toBean(sysRoleDto, SysRoleEntity.class);

		String roleId = IdUtil.simpleUUID();
		sysRoleEntity.setId(roleId);
		sysRoleEntity.setCreateUser(ContextUtil.getLoginUserId());
		sysRoleEntity.setCreateTime(new Date());

		sysRoleMapper.insert(sysRoleEntity);

		List<String> menuIds = sysRoleDto.getMenuIds();

		if(menuIds != null && menuIds.size() > 0) {

			for(String menuId : menuIds) {

				SysRoleMenuEntity roleMenu = new SysRoleMenuEntity();
				roleMenu.setRoleId(roleId);
				roleMenu.setMenuId(menuId);
				sysRoleMenuMapper.insert(roleMenu);
			}
		}

		List<SysButtonDto> buttons = MenuUtil.getButtonsFromMenuTree(sysRoleDto.getMenus());

		if(buttons != null && buttons.size() > 0) {

			for(SysButtonDto button : buttons) {

				SysRoleButtonEntity roleButton = new SysRoleButtonEntity();
				roleButton.setRoleId(roleId);
				roleButton.setMenuId(button.getMenuId());
				roleButton.setButtonId(button.getId());
				sysRoleButtonMapper.insert(roleButton);
			}
		}
	}

	@Override
	@Transactional(rollbackFor=Exception.class)
	public void update(SysRoleDto sysRoleDto) {

		SysRoleEntity role = sysRoleMapper.selectById(sysRoleDto.getId());
		BeanUtil.copyProperties(sysRoleDto, role);
		role.setUpdateUser(ContextUtil.getLoginUserId());
		role.setUpdateTime(new Date());

		// 修改角色
		sysRoleMapper.updateById(role);
		// 删除角色原有菜单权限
		LambdaQueryWrapper<SysRoleMenuEntity> roleMenuQueryWrapper = new LambdaQueryWrapper<>();
		roleMenuQueryWrapper.eq(SysRoleMenuEntity::getRoleId, sysRoleDto.getId());
		sysRoleMenuMapper.delete(roleMenuQueryWrapper);
		// 删除角色原有按钮权限
		LambdaQueryWrapper<SysRoleButtonEntity> roleButtonQueryWrapper = new LambdaQueryWrapper<>();
		roleButtonQueryWrapper.eq(SysRoleButtonEntity::getRoleId, sysRoleDto.getId());
		sysRoleButtonMapper.delete(roleButtonQueryWrapper);

		List<String> menuIds = sysRoleDto.getMenuIds();

		if(menuIds != null && menuIds.size() > 0) {

			for(String menuId : menuIds) {

				SysRoleMenuEntity roleMenu = new SysRoleMenuEntity();
				roleMenu.setRoleId(sysRoleDto.getId());
				roleMenu.setMenuId(menuId);
				sysRoleMenuMapper.insert(roleMenu);
			}
		}

		List<SysButtonDto> buttons = MenuUtil.getButtonsFromMenuTree(sysRoleDto.getMenus());

		if(buttons != null && buttons.size() > 0) {

			for(SysButtonDto button : buttons) {

				SysRoleButtonEntity roleButton = new SysRoleButtonEntity();
				roleButton.setRoleId(sysRoleDto.getId());
				roleButton.setMenuId(button.getMenuId());
				roleButton.setButtonId(button.getId());
				sysRoleButtonMapper.insert(roleButton);
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void delete(String id) {

		this.getById(id);

		Integer userCount = sysUserRoleMapper.findCountByRoleId(id);

		if(userCount > 0) {

			throw new SystemException("用户有使用该角色，无法删除");

		} else {

			// 删除角色
			sysRoleMapper.deleteById(id);
			// 删除角色原有菜单权限
			LambdaQueryWrapper<SysRoleMenuEntity> roleMenuQueryWrapper = new LambdaQueryWrapper<>();
			roleMenuQueryWrapper.eq(SysRoleMenuEntity::getRoleId, id);
			sysRoleMenuMapper.delete(roleMenuQueryWrapper);
			// 删除角色原有按钮权限
			LambdaQueryWrapper<SysRoleButtonEntity> roleButtonQueryWrapper = new LambdaQueryWrapper<>();
			roleButtonQueryWrapper.eq(SysRoleButtonEntity::getRoleId, id);
			sysRoleButtonMapper.delete(roleButtonQueryWrapper);
		}
	}

	@Override
	public Map<String, Object> findMenusByRoleId(String roleId) {

		Map<String, Object> resultMap = new HashMap<String, Object>(2);

		List<SysMenuDto> menuList = sysMenuMapper.findAllAndButtons();

		if(StrUtil.isNotEmpty(roleId)) {

			List<String> roleButtonIds = sysRoleButtonMapper.findButtonIdsByRoleId(roleId);
			MenuUtil.selectedButtonForMenuTree(menuList, roleButtonIds);

			List<String> roleMenuIds = sysRoleMenuMapper.findMenuIdsByRoleId(roleId);
			resultMap.put("roleMenuIds", roleMenuIds);
		}

		menuList = MenuUtil.getMenusForTree(menuList);
		resultMap.put("menus", menuList);

		return resultMap;
	}

	@Override
	public List<SysRoleDto> findAll() {

		List<SysRoleEntity> roleList = sysRoleMapper.selectList(null);

		return BeanUtil.copyToList(roleList, SysRoleDto.class);
	}

}
